<?php

class ServiceModelBase {
    function asXml($ignoreError=false) {
        $writer=new XMLBuilder();
        if ($ignoreError) {
            try {
                $this->toXml($writer);
            } catch (Exception  $e) {
                //echo $e;
            }
        } else {
            $this->toXml($writer);
        }
        return $writer->output();
    }
}

class XmlReaderEx {
    private $cur;
    public function __construct($root) {
        $this->cur=$root;
    }
    
    function createArrayOfNode($name,$ns='http://tempuri.org/') {
        $ans=array();
        $func=array($name, 'createFromXml');
        foreach ($this->findAll($name,$ns) as $node) {
            $ans[]=call_user_func($func,$node);
        }
        return $ans;
    }

    static function fromStr($str,$rootName,$rootNs='http://tempuri.org/') {
        $dom=new DOMDocument();
        $dom->loadXML($str);    
        $reader=new XmlReaderEx($dom);
        foreach ($reader->findAll($rootName,$rootNs) as $node) {
            return $node;
        }
        return false;
    }
    function findAll($name,$ns) {
        $ans=array();
        foreach ($this->cur->getElementsByTagNameNS($ns,$name) as $node) {
            $ans[]=new XmlReaderEx($node);
        }
        return $ans;
    }
    function getValue($name,$ns) {
        foreach ($this->cur->getElementsByTagNameNS($ns,$name) as $node) {
            return $node->nodeValue;
        }
        return '';
    }
}

class XMLBuilder {
    private $doc;
    private $cur;
    private $nsMap=array();
    public function __construct() {
        $this->cur=$this->doc=new DOMDocument();        
        $this->doc->formatOutput=true;
    }
    
    public function getPrefix($ns) {
        if (isset($this->nsMap[$ns])==false) {
            return $this->nsMap[$ns]='ns'.count($this->nsMap);
        }
        return $this->nsMap[$ns];
    }
    
    public function addElement($name,$ns) {
        $prefix=$this->getPrefix($ns);
        $node=$this->doc->createElementNS($ns, $prefix.':'.$name);
        $this->cur->appendChild($node);
        $this->cur=$node;
    }
    
    public function setElementValue($name,$ns,$value) {        
        if (is_array($value)) {
          foreach ($value as $val) {
              $this->setElementValue($name, $ns, $val);
          }
        } else if ($value instanceof ServiceModelBase) {
            $node=$this->addElement($name, $ns);
            $value->toXml($this);
            $this->endElement();
        } else {
            $prefix=$this->getPrefix($ns);
            $node=$this->doc->createElementNS($ns, $prefix.':'.$name,$value);    
            $this->cur->appendChild($node);
        }        
    }
    
    public function endElement() {
        $this->cur=$this->cur->parentNode;
    }
    
    public function output() {
        return $this->doc->saveXML();
    }
}

?>
